//
//  UtilManager.m
//  Snap
//
//  Created by 小猪向天飞 on 2018/7/7.
//  Copyright © 2018年 Facebook. All rights reserved.
//

#import "UtilManager.h"
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>

#import "ESPTouchTask.h"
#import "ESPTouchResult.h"
#import "ESP_NetUtil.h"
#import <SystemConfiguration/CaptiveNetwork.h>

#import "ESPUDPSocketClient.h"
#import "ESPUDPSocketServer.h"
#import "ESPTouchTaskParameter.h"

#import <sys/socket.h>
#import <sys/sockio.h>
#import <sys/ioctl.h>
#import <net/if.h>
#import <arpa/inet.h>

#import "PTFakeTouch.h"

NSString *statusStr = @"";
BOOL overSixtySecond = NO;

@interface EspTouchDelegateImpl : NSObject<ESPTouchDelegate>

@end

@implementation EspTouchDelegateImpl

-(void) dismissAlert:(UIAlertView *)alertView
{
  [alertView dismissWithClickedButtonIndex:[alertView cancelButtonIndex] animated:YES];
}

-(void) showAlertWithResult: (ESPTouchResult *) result{
  
  NSString *message = [NSString stringWithFormat:@"%@ is connected to the wifi" , result.bssid];
  NSLog(@"message:%@",message);
  //  NSTimeInterval dismissSeconds = 3.5;
  //  UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:title message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
  //  [alertView show];
  //  [self performSelector:@selector(dismissAlert:) withObject:alertView afterDelay:dismissSeconds];
}

-(void) onEsptouchResultAddedWithResult: (ESPTouchResult *) result
{
  NSLog(@"EspTouchDelegateImpl onEsptouchResultAddedWithResult bssid: %@", result.bssid);
  //dispatch_async(dispatch_get_main_queue(), ^{
  [self showAlertWithResult:result];
  //});
}

@end

@interface UtilManager ()

@property (nonatomic, strong) EspTouchDelegateImpl *_esptouchDelegate;

@end

@implementation UtilManager

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(getWifiConnectedSsid:(nonnull RCTResponseSenderBlock)callback){
  
  [ESP_NetUtil tryOpenNetworkPermission];
  self._esptouchDelegate = [[EspTouchDelegateImpl alloc] init];
  NSDictionary *netInfo = [self fetchNetInfo];
  self.BSSID = [netInfo objectForKey:@"BSSID"];
  NSLog(@"SSID:%@",[netInfo objectForKey:@"SSID"]);
  if ([netInfo objectForKey:@"SSID"]) {
    callback(@[[NSNull null],[netInfo objectForKey:@"SSID"]]);
  }else{
    callback(@[[NSNull null],@"尚未连接Wifi"]);
  }
  
}

RCT_EXPORT_METHOD(receiveSpecLenByte:(int)port timeout:(int)timeout expectDataLen:(int)expectDataLen callback:(nonnull RCTResponseSenderBlock)callback){
  
  NSLog(@"进入了Server");
  dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  dispatch_async(globalQ, ^{
    self._server = [[ESPUDPSocketServer alloc] initWithPort:port AndSocketTimeout:timeout];
    NSData *receiveData = nil;
    receiveData = [self._server receiveSpecLenBytes4:expectDataLen];
    NSLog(@"receiveDataSN:%@",receiveData);
    NSString *receiveStr = [self dataToHexString:receiveData];
    if (receiveStr.length == (expectDataLen * 2) || expectDataLen == 0) {
      NSLog(@"length:%lu",(unsigned long)receiveStr.length);
      receiveStr = [self converToDecimal:receiveStr];
      NSLog(@"receiveStr:%@",receiveStr);
      [self._server close];
      if (receiveStr.length != 0) {
        callback(@[[NSNull null],receiveStr]);
      }
    } else {
      [self._server close];
      [self._esptouchTask interrupt];
      [self._esptouchTask._server interrupt];
      callback(@[@"fail, 长度不符"]);
    }
  });
}

RCT_EXPORT_METHOD(createFileWithByte:(NSString *)hexStr AndFileName:(NSString *)fileName callback:(nonnull RCTResponseSenderBlock)callback) {
  NSData *musicData = [self convertHexStrToData:[hexStr substringFromIndex:46]];
  NSString *pathDocuments = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
  NSString *musicPath = [NSString stringWithFormat:@"%@/%@.wav", pathDocuments, fileName];
  [[NSFileManager defaultManager] createDirectoryAtPath:musicPath withIntermediateDirectories:YES attributes:nil error:nil];
  BOOL isSuccess = [musicData writeToFile:musicPath atomically:YES];
  if (isSuccess) {
    NSLog(@"写入成功");
    NSURL *url = [NSURL fileURLWithPath:musicPath];
    callback(@[[NSNull null], url]);
  } else {
    NSLog(@"写入失败");
    callback(@[@"存取文件失败"]);
  }
}

RCT_EXPORT_METHOD(performClick:(int)x AndY:(int)y callback:(nonnull RCTResponseSenderBlock)callback){
  NSInteger pointId = [PTFakeTouch fakeTouchId:[PTFakeTouch getAvailablePointId] AtPoint:CGPointMake(x, y) withTouchPhase:UITouchPhaseBegan];
  [PTFakeTouch fakeTouchId:pointId AtPoint:CGPointMake(x, y) withTouchPhase:UITouchPhaseEnded];
  callback(@[[NSNull null], @"点击完成"]);
}


#pragma mark ---Private Methods---
// 十六进制字符串转成NSData
- (NSData *)convertHexStrToData:(NSString *)str {
  
  if (!str || [str length] == 0) {
    return nil;
  }
  
  NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];
  NSRange range;
  if ([str length] % 2 == 0) {
    range = NSMakeRange(0, 2);
  } else {
    range = NSMakeRange(0, 1);
  }
  for (NSInteger i = range.location; i < [str length]; i += 2) {
    unsigned int anInt;
    NSString *hexCharStr = [str substringWithRange:range];
    NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
    
    [scanner scanHexInt:&anInt];
    NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
    [hexData appendData:entity];
    
    range.location += range.length;
    range.length = 2;
  }
  
  return hexData;
  
}

- (void)hasOverTime{
  
  overSixtySecond = YES;
  [self.overTimer invalidate];
  self.overTimer = nil;
}

- (NSString *)converToDecimal:(NSString *)theCoverString{
  
  NSString *lastStr = @"";
  for (int i = 0; i < theCoverString.length / 2; i++) {
    NSString *firstStr = [theCoverString substringWithRange:NSMakeRange(i * 2, 1)];
    NSString *secondStr = [theCoverString substringWithRange:NSMakeRange(i * 2 + 1, 1)];
    int firstNum = [[self changeToNumber:firstStr] intValue];
    int secondNum = [[self changeToNumber:secondStr] intValue];
    int finalNum = firstNum * 16 + secondNum;
    NSString *asciiCode = [NSString stringWithFormat:@"%c",finalNum];
    lastStr = [NSString stringWithFormat:@"%@%@",lastStr,asciiCode];
  }
  return lastStr;
}

- (NSString *)changeToNumber:(NSString *)changeStr{
  
  NSString *rStr = @"";
  if ([changeStr isEqualToString:@"A"] || [changeStr isEqualToString:@"a"]) {
    rStr = @"10";
  }else if ([changeStr isEqualToString:@"B"] || [changeStr isEqualToString:@"b"]) {
    rStr = @"11";
  }else if ([changeStr isEqualToString:@"C"] || [changeStr isEqualToString:@"c"]) {
    rStr = @"12";
  }else if ([changeStr isEqualToString:@"D"] || [changeStr isEqualToString:@"d"]) {
    rStr = @"13";
  }else if ([changeStr isEqualToString:@"E"] || [changeStr isEqualToString:@"e"]) {
    rStr = @"14";
  }else if ([changeStr isEqualToString:@"F"] || [changeStr isEqualToString:@"f"]) {
    rStr = @"15";
  }else{
    rStr = changeStr;
  }
  return rStr;
  
}

- (NSString *)dataToHexString:(NSData *)data{
  
  Byte *bytes = (Byte *)[data bytes];
  
  NSString *hexStr = @"";
  
  for (int i = 0; i < [data length]; i++) {
    NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i]&0xff];
    if ([newHexStr length] == 1) {
      hexStr = [NSString stringWithFormat:@"%@0%@",hexStr,newHexStr];
    }else{
      hexStr = [NSString stringWithFormat:@"%@%@",hexStr,newHexStr];
    }
  }
  
  return hexStr;
  
}

- (NSString *)getDeviceIPIpAddresses{
  
  int sockfd =socket(AF_INET,SOCK_DGRAM, 0);
  
  //    if (sockfd <</span> 0) return nil;
  
  NSMutableArray *ips = [NSMutableArray array];
  
  int BUFFERSIZE = 4096;
  
  struct ifconf ifc;
  
  char buffer[BUFFERSIZE], *ptr, lastname[IFNAMSIZ], *cptr;
  
  struct ifreq *ifr, ifrcopy;
  
  ifc.ifc_len = BUFFERSIZE;
  
  ifc.ifc_buf = buffer;
  
  if (ioctl(sockfd,SIOCGIFCONF, &ifc) >= 0){
    
    for (ptr = buffer; ptr < buffer + ifc.ifc_len; ){
      
      ifr = (struct ifreq *)ptr;
      
      int len =sizeof(struct sockaddr);
      
      if (ifr->ifr_addr.sa_len > len) {
        
        len = ifr->ifr_addr.sa_len;
        
      }
      
      ptr += sizeof(ifr->ifr_name) + len;
      
      if (ifr->ifr_addr.sa_family !=AF_INET) continue;
      
      if ((cptr = (char *)strchr(ifr->ifr_name,':')) != NULL) *cptr =0;
      
      if (strncmp(lastname, ifr->ifr_name,IFNAMSIZ) == 0)continue;
      
      memcpy(lastname, ifr->ifr_name,IFNAMSIZ);
      
      ifrcopy = *ifr;
      
      ioctl(sockfd,SIOCGIFFLAGS, &ifrcopy);
      
      if ((ifrcopy.ifr_flags &IFF_UP) == 0)continue;
      
      NSString *ip = [NSString stringWithFormat:@"%s",inet_ntoa(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr)];
      
      [ips addObject:ip];
      
    }
    
  }
  
  close(sockfd);
  
  NSString *deviceIP =@"";
  
  for (int i=0; i < ips.count; i++){
    
    if (ips.count >0){
      
      deviceIP = [NSString stringWithFormat:@"%@",ips.lastObject];
    }
    
  }
  
  NSLog(@"deviceIP========%@",deviceIP);
  return deviceIP;
  
}

- (void)initParameter{
  
  self._parameter = [[ESPTouchTaskParameter alloc] init];
  NSString *localInetAddr4 = [ESP_NetUtil getLocalIPv4];
  if (![ESP_NetUtil isIPv4PrivateAddr:localInetAddr4]) {
    localInetAddr4 = nil;
  }
  NSString *localInetAddr6 = [ESP_NetUtil getLocalIPv6];
  [self._parameter setIsIPv4Supported:localInetAddr4!=nil];
  [self._parameter setIsIPv6Supported:localInetAddr6!=nil];
}

- (NSDictionary *)fetchNetInfo{
  
  NSArray *interfaceNames = CFBridgingRelease(CNCopySupportedInterfaces());
  //    NSLog(@"%s: Supported interfaces: %@", __func__, interfaceNames);
  
  NSDictionary *SSIDInfo;
  for (NSString *interfaceName in interfaceNames) {
    SSIDInfo = CFBridgingRelease(
                                 CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName));
    //        NSLog(@"%s: %@ => %@", __func__, interfaceName, SSIDInfo);
    
    BOOL isNotEmpty = (SSIDInfo.count > 0);
    if (isNotEmpty) {
      break;
    }
  }
  return SSIDInfo;
}

- (void) tapConfirmForResults:(NSString *)apSsid apPassword:(NSString *)apPassword apBssid:(NSString *)apBssid taskResultCountStr:(NSString *)taskResultCountStr{
  // do confirm
  
  NSLog(@"ESPViewController do confirm action...");
  //dispatch_queue_t  queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  //dispatch_async(queue, ^{
  NSLog(@"ESPViewController do the execute work...");
  // execute the task
  NSArray *esptouchResultArray = [self executeForResults:apSsid apPassword:apPassword apBssid:apBssid taskResultCountStr:taskResultCountStr];
  // show the result to the user in UI Main Thread
  //dispatch_async(dispatch_get_main_queue(), ^{
  
  ESPTouchResult *firstResult = [esptouchResultArray objectAtIndex:0];
  // check whether the task is cancelled and no results received
  if (!firstResult.isCancelled)
  {
    NSMutableString *mutableStr = [[NSMutableString alloc]init];
    NSUInteger count = 0;
    // max results to be displayed, if it is more than maxDisplayCount,
    // just show the count of redundant ones
    const int maxDisplayCount = 5;
    if ([firstResult isSuc])
    {
      
      for (int i = 0; i < [esptouchResultArray count]; ++i)
      {
        ESPTouchResult *resultInArray = [esptouchResultArray objectAtIndex:i];
        [mutableStr appendString:[resultInArray description]];
        [mutableStr appendString:@"\n"];
        count++;
        if (count >= maxDisplayCount)
        {
          break;
        }
      }
      
      if (count < [esptouchResultArray count])
      {
        [mutableStr appendString:[NSString stringWithFormat:@"\nthere's %lu more result(s) without showing\n",(unsigned long)([esptouchResultArray count] - count)]];
      }
      //[[[UIAlertView alloc]initWithTitle:@"Execute Result" message:mutableStr delegate:nil cancelButtonTitle:@"I know" otherButtonTitles:nil] show];
    }
    
    else
    {
      statusStr = @"Esptouch fail";
      //[[[UIAlertView alloc]initWithTitle:@"Execute Result" message:@"Esptouch fail" delegate:nil cancelButtonTitle:@"I know" otherButtonTitles:nil] show];
    }
  }
  
  //});
  //});
}

- (NSArray *)executeForResults:(NSString *)apSsid apPassword:(NSString *)apPassword apBssid:(NSString *)apBssid taskResultCountStr:(NSString *)taskResultCountStr{
  
  //  self._condition = [[NSCondition alloc]init];
  //  [self._condition lock];
  int taskCount = [taskResultCountStr intValue];
  self._esptouchTask = [[ESPTouchTask alloc] initWithApSsid:apSsid andApBssid:apBssid andApPwd:apPassword];
  // set delegate
  [self._esptouchTask setEsptouchDelegate:self._esptouchDelegate];
  //[self._condition unlock];
  
  NSArray * esptouchResults = [self._esptouchTask executeForResults:taskCount];
  NSLog(@"EsptouchManager executeForResult() result is: %@",esptouchResults);
  self.resultArray = [esptouchResults copy];
  statusStr = @"success";
  return esptouchResults;
}


@end
